package com.piece.file.client;

import com.piece.file.enums.FileStorageType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.util.Assert;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 文件客户端的工厂实现类
 */
@Slf4j
public class FileClientFactoryImpl implements FileClientFactory {

    /**
     * 文件客户端集合
     */
    private final ConcurrentMap<String, AbstractFileClient<?>> clients = new ConcurrentHashMap<>();

    /**
     * 默认文件客户端
     */
    private String clientType;

    public FileClientFactoryImpl(String clientType) {
        this.clientType = clientType;
    }

    @Override
    public void changeClientType(String clientType) {
        this.clientType = clientType;
    }

    @Override
    public FileClient get() {
        FileClient client = get(FileStorageType.getByStorage(this.clientType));
        if (null == client) {
            FileStorageType[] types = FileStorageType.values();
            for (FileStorageType type : types) {
                client = clients.get(type.getName());
                if (null != client) {
                    return client;
                }
            }
        }

        return client;
    }

    @Override
    public FileClient get(FileStorageType storage) {
        AbstractFileClient<?> client = clients.get(storage.getName());
        if (null == client) {
            log.error("[找不到({})文件客户端]", storage.getName());
        }
        return client;
    }

    @Override
    public FileClient getNative() {
        return clients.get(FileStorageType.NATIVE.getName());
    }

    @Override
    public <Config extends FileClientConfig> void init(String storage, Config config) {
        AbstractFileClient<Config> client = (AbstractFileClient<Config>) clients.get(storage);
        if (null == client) {
            client = this.createFileClient(storage, config);
            client.init();
            clients.put(storage, client);
        } else {
            client.refresh(config);
        }
    }

    private <Config extends FileClientConfig> AbstractFileClient<Config> createFileClient(String storage, Config config) {
        FileStorageType storageType = FileStorageType.getByStorage(storage);
        Assert.notNull(storageType, String.format("文件配置(%s) 为空", storageType));
        return (AbstractFileClient<Config>) ReflectUtils.newInstance(storageType.getClientClass(), new Class[]{storage.getClass(), config.getClass()}, new Object[]{storage, config});
    }
}
